package com.herui.ota.service.iml;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.herui.ota.entity.User;
import com.herui.ota.enums.ResponseEnum;
import com.herui.ota.enums.UserAccountState;
import com.herui.ota.exception.ServiceException;
import com.herui.ota.pojo.form.UserFilterForm;
import com.herui.ota.pojo.vo.UserCache;
import com.herui.ota.pojo.vo.UserVo;
import com.herui.ota.utils.DownloadUtil;
import com.herui.ota.utils.ExcelFileUtil;
import com.mlnx.common.entity.BaseEntity;
import com.mlnx.common.form.PageForm;
import com.mlnx.common.utils.MyLog;
import org.apache.commons.lang3.StringUtils;
import org.shan.base.layer.user.entity.UserRole;
import org.shan.base.layer.user.enums.MenuType;
import org.shan.base.layer.user.pojo.vo.RoleVo;
import org.shan.base.layer.user.service.RoleService;
import org.shan.base.layer.user.service.UserAccountService;
import org.shan.base.layer.user.service.UserRoleService;
import org.shan.spring.base.utils.ServletUtils;
import org.shan.spring.cache.CacheChannel;
import org.shan.spring.mybatis.service.BaseCurdService;
import org.shan.spring.redis.RedisUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by amanda.shan on 2019/7/15.
 */
public class BaseService<M extends BaseMapper<T>, T> extends BaseCurdService<M, T> {

    @Autowired
    private PasswordEncoder encoder;

    @Autowired
    protected UserAccountService userAccountService;
    @Autowired
    protected UserRoleService userRoleService;
    @Autowired
    protected LightUserAccountServiceIml lightUserAccountServiceIml;

    @Autowired
    private RoleService roleService;

    protected MyLog log = MyLog.getLog(getClass());

    public static boolean Test_Flag = false;
    public static String User_Name = "o1spL5BmH5C_Y_IEOdjm5U0QAjto";

    @Autowired
    protected CacheChannel cacheChannel;

    @Autowired
    protected RedisUtil redisUtil;

    protected void evict(String region, String key) {
        cacheChannel.evict(region, key);
        log.debug("删除 {} {} 的缓存数据", region, key);
    }

    protected void clear(String region) {
//        cacheChannel.clear(region);
    }

    public String getUsername() {

        if (Test_Flag) {
            return User_Name;
        }

        Object username = ServletUtils.getAttribute("username");
        if (username != null || !"anonymousUser".equals(username)) {
            return username.toString();
        } else {
            return null;
        }
    }

    protected List<String> getRights(){

        List<String> rights = new LinkedList<>();

        RoleVo roleVo = roleService.getByUserId(getUserId());
        roleVo.getMenus().stream().forEach(menu -> {
            MenuType type = menu.getType();
            if (type.equals(MenuType.RIGHT)){
                rights.add(menu.getMenuKey());
            }
        });

        return rights;
    }

    public boolean checkRight(String... rights){
        List<String> strings = getRights();
        if (strings != null){
            for (int i = 0; i < rights.length; i++) {
                if (!strings.contains(rights[i])){
                    throw new ServiceException(ResponseEnum.ROLE_NO);
                }
            }
            return true;
        }else{
            throw new ServiceException(ResponseEnum.ROLE_NO);
        }
    }

    protected boolean checkRightIn(String... rights){
        List<String> strings = getRights();
        if (strings != null){
            for (int i = 0; i < rights.length; i++) {
                if (strings.contains(rights[i])){
                    return true;
                }
            }
            throw new ServiceException(ResponseEnum.ROLE_NO);
        }else{
            throw new ServiceException(ResponseEnum.ROLE_NO);
        }
    }


    /**
     * 包装 插入创建者和创建时间
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T extends BaseEntity> T wrapperCreater(T t) {
        Object username = null;
        try {
            username = ServletUtils.getAttribute("username");
        } catch (Exception e) {

        }
        if (username != null) {
            t.setCreater(username.toString());
        }
        t.setCreateTime(new Date());

        return t;
    }

    /**
     * 包装 插入创建者和创建时间
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T extends BaseEntity> T wrapperEditor(T t) {

        String username = null;
        try {
            username = ServletUtils.getAttribute("username");
        } catch (Exception e) {
//            e.printStackTrace();
        }
        if (username != null) {
            t.setEditor(username.toString());
        }
        t.setEditTime(new Date());

        return t;
    }

    public void pageExcel(PageForm pageForm, Object filter, HttpServletResponse response) throws IllegalAccessException {
        // 创建一个SimpleDateFormat对象，定义时间的格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        IPage page = page(pageForm, filter);
        List records = page.getRecords();

        byte[] excel = ExcelFileUtil.createExcel(records);
        DownloadUtil.downloadExcel(response, excel);
    }

    @Override
    public void save(T entity) {
        if (entity instanceof BaseEntity){
            BaseEntity baseEntity = (BaseEntity) entity;
            super.save((T) this.<BaseEntity>wrapperCreater(baseEntity));
        }else{
            super.save(entity);
        }
    }

    @Override
    public boolean updateById(T entity) {
        if (entity instanceof BaseEntity){
            BaseEntity baseEntity = (BaseEntity) entity;
            return super.updateById((T) this.<BaseEntity>wrapperEditor(baseEntity));
        }else{
            return super.updateById(entity);
        }
    }

    /**
     * 推送消息
     *
     * @param channel 消息的key
     * @param message 消息的内容，可以是一个任意对象， 会将其转化为json数据传输， 收到的永远是string
     */
    public void push(String channel, Object message) {
        redisUtil.push(channel, message);
    }

    public Integer getUserId() {

        UserCache userCache = lightUserAccountServiceIml.getUserCache(false);
        return userCache.getId();
    }

    public String getWxOpenid(){
        UserCache userCache = lightUserAccountServiceIml.getUserCache(false);
        if (userCache != null) {
            RoleVo role = userCache.getRoleVo();
            if (role.getRoleKey().equals("subcustomer")){
                User info = (User) userCache.getInfo();
                return info.getWxOpenid();
            }
        }
        return null;
    }

    protected int saveAccount(String username, String password, Integer roleId, String identity){
        org.shan.base.layer.user.entity.UserAccount account = userAccountService.findByUsername(username);

        if (account != null) {
            return account.getId();
        }
        account= new org.shan.base.layer.user.entity.UserAccount();
        // 保存账户
        account.setUsername(username);
        account.setPassword(encoder.encode(password));
        account.setIdentity(identity);
        account.setState(UserAccountState.NORMAL.toString());
        userAccountService.save(account);

        // 保存角色
        UserRole userRole = new UserRole();
        userRole.setUserId(account.getId());
        userRole.setRoleId(roleId);
        userRoleService.save(userRole);

        return account.getId();
    }

    protected void updateAccount(Integer id, String password, Integer roleId){
        // 更改用户角色
        if (roleId != null){
            userRoleService.changeUserRole(id, new Integer[]{roleId});
        }
        // 更改密码
        if (!StringUtils.isEmpty(password)){
            org.shan.base.layer.user.entity.UserAccount account = new org.shan.base.layer.user.entity.UserAccount();
            account.setId(id);
            account.setPassword(encoder.encode(password));
            userAccountService.updateById(account);
        }
    }
}
